#pragma once
#include <semaphore.h>
#include <vector>
#include <iostream>
#include <unistd.h>
#define CAPACITY 8
using namespace std;
template <class T>
class RingQueue
{
public:
    RingQueue(uint32_t capacity = CAPACITY)
        : _ringQueue(capacity), _capacity(capacity), _pIndex(0), _cIndex(0)
    {
        sem_init(&_roomSem, 0, _capacity);
        sem_init(&_dataSem, 0, 0);
        pthread_mutex_init(&_pmutex,nullptr);
        pthread_mutex_init(&_cmutex,nullptr);
    }
    ~RingQueue()
    {
        sem_destroy(&_roomSem);
        sem_destroy(&_dataSem);
        pthread_mutex_destroy(&_pmutex);
        pthread_mutex_destroy(&_cmutex);
    }
    void push(T &data) // 生产者生产数据
    {
        sem_wait(&_roomSem); // 申请空间资源,--roomSem

        pthread_mutex_lock(&_pmutex);
        _ringQueue[_pIndex] = data;
        _pIndex++;
        _pIndex %= _capacity;
        cout << "生产者[" << pthread_self() << "]:生产了一个数据：" << data << endl;//便于观察
        pthread_mutex_unlock(&_pmutex);

        sem_post(&_dataSem); // 释放数据资源,++dataSem
    }
    void pop(T &data) // 消费者消费数据,输出型参数
    {
        sem_wait(&_dataSem); // 申请数据资源,--dataSem

        pthread_mutex_lock(&_cmutex);
        data = _ringQueue[_cIndex];
        ++_cIndex;
        _cIndex %= _capacity;
        cout << "消费者[" << pthread_self() << "]:消费了一个数据：" << data << endl;//便于观察
        pthread_mutex_unlock(&_cmutex);

        sem_post(&_roomSem); // 释放空间资源,++roomSem
    }

private:
    vector<T> _ringQueue;    // 环形队列
    uint32_t _capacity;      // 环形队列大小
    sem_t _roomSem;          // 空间资源个数
    sem_t _dataSem;          // 数据资源个数
    uint32_t _pIndex;        // 表示生产者正在生产的位置
    uint32_t _cIndex;        // 表示消费者正在消费的位置
    pthread_mutex_t _pmutex; // 生产者的锁
    pthread_mutex_t _cmutex; // 消费者的锁
};